#include "stm32f10x.h"
#include "OLED_Font.h"
#include "delay.h"
#include "character.h"
#include "oled.h"

/*引脚配置*/
#define OLED_W_SCL(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)(x))
#define OLED_W_SDA(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)(x))

/*引脚初始化*/
void OLED_I2C_Init(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void OLED_I2C_Start(void)
{
	OLED_W_SDA(1);
	OLED_W_SCL(1);
	OLED_W_SDA(0);
	OLED_W_SCL(0);
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void OLED_I2C_Stop(void)
{
	OLED_W_SDA(0);
	OLED_W_SCL(1);
	OLED_W_SDA(1);
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的一个字节
  * @retval 无
  */
void OLED_I2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i++)
	{
		OLED_W_SDA(Byte & (0x80 >> i));
		OLED_W_SCL(1);
		OLED_W_SCL(0);
	}
	OLED_W_SCL(1);	//额外的一个时钟，不处理应答信号
	OLED_W_SCL(0);
}

/**
  * @brief  OLED写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void OLED_WriteCommand(uint8_t Command)
{
	OLED_I2C_Start();
	OLED_I2C_SendByte(0x78);		//从机地址
	OLED_I2C_SendByte(0x00);		//写命令
	OLED_I2C_SendByte(Command); 
	OLED_I2C_Stop();
}

/**
  * @brief  OLED写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void OLED_WriteData(unsigned char Data)
{
	OLED_I2C_Start();
	OLED_I2C_SendByte(0x78);		//从机地址
	OLED_I2C_SendByte(0x40);		//写数据
	OLED_I2C_SendByte(Data);
	OLED_I2C_Stop();
}

/**
  * @brief  OLED设置光标位置
  * @param  Y 以左上角为原点，向下方向的坐标，范围：0~7
  * @param  X 以左上角为原点，向右方向的坐标，范围：0~127
  * @retval 无
  */
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
	OLED_WriteCommand(0xB0 | Y);					//设置Y位置
	OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));	//设置X位置高4位
	OLED_WriteCommand(0x00 | (X & 0x0F));			//设置X位置低4位
}

void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
{ 
    OLED_WriteCommand(0xb0+y);
    OLED_WriteCommand(((x&0xf0)>>4)|0x10);
    OLED_WriteCommand((x&0x0f)|0x01);
}


//图
void oled_setpos(unsigned char x,unsigned char y)
{
	OLED_WriteCommand(0xb0+y);
	OLED_WriteCommand((((x+2)&0xf0)>>4)|0x10);
	OLED_WriteCommand(((x+2)&0x0f));
}

/**
  * @brief  OLED清屏
  * @param  无
  * @retval 无
  */
void OLED_Clear(void)
{  
	uint8_t i, j;
	for (j = 0; j < 8; j++)
	{
		OLED_SetCursor(j, 0);
		for(i = 0; i < 128; i++)
		{
			OLED_WriteData(0x00);
		}
	}
}

/**
//  * @brief  OLED显示一个字符
//  * @param  Line 行位置，范围：1~4
//  * @param  Column 列位置，范围：1~16
//  * @param  Char 要显示的一个字符，范围：ASCII可见字符
//  * @retval 无
  */
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{      	
	uint8_t i;
	OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);		//设置光标位置在上半部分
	for (i = 0; i < 8; i++)
	{
		OLED_WriteData(OLED_F8x16[Char - ' '][i]);			//显示上半部分内容
	}
	OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);	//设置光标位置在下半部分
	for (i = 0; i < 8; i++)
	{
		OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);		//显示下半部分内容
	}
}

void OLED_Char(unsigned char x, unsigned char y, unsigned char c)
{
			unsigned char i = 0;
			c = c - 32;
			if(x > 126)
      {
         x = 0;
         y++;
      }
      OLED_SetCursor(x,y);
			for(i=0;i<6;i++)
      OLED_WriteData(F6x8[c][i]);
      x += 6;
			
}

//  * @brief  OLED显示字符串
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
    unsigned char c = 0,i = 0,j = 0;
    switch(TextSize)
    {
        case 1:
        {
            while(ch[j] != '\0')
            {
                c = ch[j] - 32;
                if(x > 126)
                {
                    x = 0;
                    y++;
                }
                OLED_SetPos(x,y);
                for(i=0;i<6;i++)
                    OLED_WriteData(F6x8[c][i]);
                x += 6;
                j++;
            }
        }break;
        case 2:
        {
            while(ch[j] != '\0')
            {
                c = ch[j] - 32;
                if(x > 120)
                {
                    x = 0;
                    y++;
                }
                OLED_SetPos(x,y);
                for(i=0;i<8;i++)
                    OLED_WriteData(F8X16[c*16+i]);
                OLED_SetPos(x,y+1);
                for(i=0;i<8;i++)
                    OLED_WriteData(F8X16[c*16+i+8]);
                x += 8;
                j++;
            }
        }break;
    }
}

/**
  * @brief  OLED次方函数
  * @retval 返回值等于X的Y次方
  */
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y--)
	{
		Result *= X;
	}
	return Result;
}

/**
  * @brief  OLED显示数字（十进制，正数）
  * @param  Line 起始行位置，范围：1~4
  * @param  Column 起始列位置，范围：1~16
  * @param  Number 要显示的数字，范围：0~4294967295
  * @param  Length 要显示数字的长度，范围：1~10
  * @retval 无
  */
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i++)							
	{
		OLED_Char(Line, Column + i*6, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
	}
}

/**
  * @brief  OLED显示数字（十进制，带符号数）
  */
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
	uint8_t i;
	uint32_t Number1;
	if (Number >= 0)
	{
		OLED_Char(Line, Column, '+');
		Number1 = Number;
	}
	else
	{
		OLED_Char(Line, Column, '-');
		Number1 = -Number;
	}
	for (i = 0; i < Length; i++)							
	{
		OLED_Char(Line, Column + (i + 1)*6, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
	}
}

/*
描述：显示浮点数(可显示正负数)（-65535~65535）
输入：
	x:显示的x起始位置
	y:显示的y起始位置
	num:要显示的数字
	Char_Size:要显示数字的大小
局限：目前只能显示确定范围的小数，且小数部分显示不准确
*/
void OLED_ShowFloatNumber(u8 x,u8 y,float num)
{
	unsigned char zheng_len=0,xiao_len=0,polarity_flag=0;
	int zheng=0,xiao=0;		//经读者“迷迷惘惘”提醒，为这两行局部变量赋值
	//附注：为防止程序运行过程中程序行为异常，需要对局部变量赋值
	if(num>0)
		polarity_flag=1;
	else
	{
		polarity_flag=0;
		num=-num;
	}
	zheng=(int)num;
	xiao=((num-zheng)*100)/1;	//显示小数点后两位
	while(zheng)	//计算整数部分位数
	{
		zheng_len++;
		zheng/=10;
	}
	xiao_len=2;
	zheng=(int)num;	//在计算整数部分数值时，原赋值被篡改，这里重新赋值
	if(polarity_flag)
	{	
			OLED_ShowNum(x,y,zheng,zheng_len);
			OLED_Char(x,y+zheng_len*6,'.');
			OLED_ShowNum(x,y+(zheng_len+1)*6,xiao,xiao_len);
		}
	else
	{
			OLED_Char(x,y,'-');
			OLED_ShowNum(x,y+6,zheng,zheng_len);
			OLED_Char(x,y+(zheng_len+1)*6,'.');
			OLED_ShowNum(x,y+(zheng_len+2)*6,xiao,xiao_len);
		}
}


/**
  * @brief  OLED显示数字（十六进制，正数）
  * @param  Line 起始行位置，范围：1~4
  * @param  Column 起始列位置，范围：1~16
  * @param  Number 要显示的数字，范围：0~0xFFFFFFFF
  * @param  Length 要显示数字的长度，范围：1~8
  * @retval 无
  */
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i, SingleNumber;
	for (i = 0; i < Length; i++)							
	{
		SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
		if (SingleNumber < 10)
		{
			OLED_ShowChar(Line, Column + i, SingleNumber + '0');
		}
		else
		{
			OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
		}
	}
}

/**
  * @brief  OLED显示数字（二进制，正数）
  * @param  Line 起始行位置，范围：1~4
  * @param  Column 起始列位置，范围：1~16
  * @param  Number 要显示的数字，范围：0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度，范围：1~16
  * @retval 无
  */
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i++)							
	{
		OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
	}
}

//显示图片
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
    unsigned int j=0;
    unsigned char x,y;

  if(y1%8==0)
        y = y1/8;
  else
        y = y1/8 + 1;
    for(y=y0;y<y1;y++)
    {
        OLED_SetPos(x0,y);
    for(x=x0;x<x1;x++)
        {
            OLED_WriteData(BMP[j++]);
        }
    }
}

void OLED_AE86_Init(void)
{
		OLED_ShowStr(17,0,"***AE86 Init***",1);
		OLED_ShowStr(1,2,"UARTX:",1);
		OLED_ShowStr(1,3,"TIMX:",1);
		OLED_ShowStr(1,4,"TRACK:",1);
		OLED_ShowStr(1,5,"JY931:",1);
		OLED_ShowStr(1,6,"DHT11:",1);
		OLED_ShowStr(1,7,"WIFI:",1);
}

void OLED_HD(void)
{
		
		OLED_WriteCommand(0x26); //向右滚动，27则向左
		OLED_WriteCommand(0x00); //虚拟字节
		OLED_WriteCommand(0x00); //起始页 
		OLED_WriteCommand(0x07); //滚动速度
		OLED_WriteCommand(0x00); //终止页 
		OLED_WriteCommand(0x00); //虚拟字节
		OLED_WriteCommand(0xFF); //虚拟字节
		OLED_WriteCommand(0x2F); //开启滚动
}

void OLED_BMP(void)
{
		OLED_WriteCommand(0x26); //向右滚动，27则向左
		OLED_WriteCommand(0x00); //虚拟字节
		OLED_WriteCommand(0x00); //起始页 
		OLED_WriteCommand(0x07); //滚动速度
		OLED_WriteCommand(0x07); //终止页 
		OLED_WriteCommand(0x00); //虚拟字节
		OLED_WriteCommand(0xFF); //虚拟字节
		OLED_WriteCommand(0x2F); //开启滚动
		OLED_DrawBMP(0,0,128,8,bmp);

}

extern int U1;
extern int U2;
extern int U3;
extern int U4;
extern int U5;
extern int T1;
extern int T2;
extern int T3;
extern int T4;
extern int TRACK;
extern int JY931;
extern int DHT11;
extern int WIFI;
void OLED_AE86(void)
{		
		OLED_Clear();
		OLED_HD();
		OLED_AE86_Init();
		OLED_ShowStr(40,1,"1",1);
		OLED_ShowStr(54,1,"2",1);
		OLED_ShowStr(68,1,"3",1);
		OLED_ShowStr(82,1,"4",1);
		OLED_ShowStr(96,1,"5",1);
		if(U1==1) OLED_ShowStr(40,2,"OK",1);
		else OLED_ShowStr(40,2,"NO",1);
		if(U2==1) OLED_ShowStr(54,2,"OK",1);
		else OLED_ShowStr(54,2,"NO",1);
		if(U3==1) OLED_ShowStr(68,2,"OK",1);
		else OLED_ShowStr(68,2,"NO",1);
		if(U4==1) OLED_ShowStr(82,2,"OK",1);
		else OLED_ShowStr(82,2,"NO",1);
		if(U5==1) OLED_ShowStr(96,2,"OK",1);
		else OLED_ShowStr(96,2,"NO",1);
		if(T1==1) OLED_ShowStr(40,3,"OK",1);
		else OLED_ShowStr(40,3,"NO",1);
		if(T2==1) OLED_ShowStr(54,3,"OK",1);
		else OLED_ShowStr(54,3,"NO",1);
		if(T3==1) OLED_ShowStr(68,3,"OK",1);
		else OLED_ShowStr(68,3,"NO",1);
		if(T4==1) OLED_ShowStr(82,3,"OK",1);
		else OLED_ShowStr(82,3,"NO",1);
		if(TRACK==1)OLED_ShowStr(42,4,"OK",1);
		else OLED_ShowStr(42,4,"NO",1);
		if(JY931==1)OLED_ShowStr(42,5,"OK",1);
		else OLED_ShowStr(42,5,"NO",1);
		if(DHT11==1)OLED_ShowStr(42,6,"OK",1);
		else OLED_ShowStr(42,6,"NO",1);
		if(WIFI==1)OLED_ShowStr(42,7,"OK",1);
		else OLED_ShowStr(42,7,"NO",1);
		delay_ms(3000);
		delay_ms(3000);
		delay_ms(3000);
		OLED_Clear();
}





extern int Encoder_A,Encoder_B,Encoder_C,Encoder_D,error;
extern u8 dat[5];
extern float fAngle[3];
extern float P1;

extern int im;
void OLED_KE(void)
{			         
	OLED_WriteCommand(0x2E); //关闭滚动
	OLED_ShowStr(17,0,"***AE86 PULS***",1);
	OLED_ShowStr(1,2,"ERROR: ",1);
	OLED_ShowStr(1,3,"VelocityA:",1);
	OLED_ShowStr(1,4,"VelocityB:",1);
	OLED_ShowStr(1,5,"VelocityC:",1);
	OLED_ShowStr(1,6,"VelocityD:",1);

	OLED_ShowStr(84,2,"angle:",1);
	OLED_ShowStr(84,4,"X",1);
	OLED_ShowStr(84,5,"Y",1);
	OLED_ShowStr(84,6,"Z",1);

	OLED_ShowStr(1,7,"hum:",1);
	OLED_ShowStr(60,7,"tem:",1);
	
	OLED_ShowStr(78,2,"!",1);
	OLED_ShowStr(78,3,"!",1);
	OLED_ShowStr(78,4,"!",1);
	OLED_ShowStr(78,5,"!",1);
	OLED_ShowStr(78,6,"!",1);
	
	OLED_ShowSignedNum(2,42,error,4);
	OLED_ShowSignedNum(3,61,Encoder_A,2);
	OLED_ShowSignedNum(4,61,Encoder_B,2);
	OLED_ShowSignedNum(5,61,Encoder_C,2);
	OLED_ShowSignedNum(6,61,Encoder_D,2);

	OLED_ShowFloatNumber(4,92,fAngle[0]);
	OLED_ShowFloatNumber(5,92,fAngle[1]);
	OLED_ShowFloatNumber(6,92,fAngle[2]);

	OLED_ShowNum(7,25,dat[0],2);
	OLED_ShowStr(36,7,".",1);
	OLED_ShowNum(7,42,dat[1],2);

	OLED_ShowNum(7,84,dat[2],2);
	OLED_ShowStr(96,7,".",1);
	OLED_ShowNum(7,102,dat[3],2);
	//OLED_WriteCommand(0x2F); //开启滚动
}
/**
  * @brief  OLED初始化
  * @param  无
  * @retval 无
  */
void OLED_Init(void)
{
	uint32_t i, j;
	
	for (i = 0; i < 1000; i++)			//上电延时
	{
		for (j = 0; j < 1000; j++);
	}
	
	OLED_I2C_Init();			//端口初始化
	
	OLED_WriteCommand(0xAE);	//关闭显示
	
	OLED_WriteCommand(0xD5);	//设置显示时钟分频比/振荡器频率
	OLED_WriteCommand(0x80);
	
	OLED_WriteCommand(0xA8);	//设置多路复用率
	OLED_WriteCommand(0x3F);
	
	OLED_WriteCommand(0xD3);	//设置显示偏移
	OLED_WriteCommand(0x00);
	
	OLED_WriteCommand(0x40);	//设置显示开始行
	
	OLED_WriteCommand(0xA1);	//设置左右方向，0xA1正常 0xA0左右反置
	
	OLED_WriteCommand(0xC8);	//设置上下方向，0xC8正常 0xC0上下反置

	OLED_WriteCommand(0xDA);	//设置COM引脚硬件配置
	OLED_WriteCommand(0x12);
	
	OLED_WriteCommand(0x81);	//设置对比度控制
	OLED_WriteCommand(0xCF);

	OLED_WriteCommand(0xD9);	//设置预充电周期
	OLED_WriteCommand(0xF1);

	OLED_WriteCommand(0xDB);	//设置VCOMH取消选择级别
	OLED_WriteCommand(0x30);

	OLED_WriteCommand(0xA4);	//设置整个显示打开/关闭

	OLED_WriteCommand(0xA6);	//设置正常/倒转显示

	OLED_WriteCommand(0x8D);	//设置充电泵
	OLED_WriteCommand(0x14);

	OLED_WriteCommand(0xAF);	//开启显示
		
	OLED_Clear();				//OLED清屏
}
